#include "sht4x.h"
#include "i2cDrive.h"

#define SHT_ADDR 	0x88			//7位ID为0x44，第8位为读写位

mI2CTypedef_t ShtI2c;				//io模拟i2c接口


//硬件接口
static void i2c_SdaH(void){
	HAL_GPIO_SetInOut(GPIOD, GPIO_PIN_6, ENABLE, DISABLE);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_6, GPIO_PIN_RESET);
}

static void i2c_SdaL(void){
	HAL_GPIO_SetInOut(GPIOD, GPIO_PIN_6, ENABLE, ENABLE);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_6, GPIO_PIN_RESET);
}

static void i2c_SclH(void){
	HAL_GPIO_SetInOut(GPIOD,GPIO_PIN_7, ENABLE, DISABLE);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET);
}

static void i2c_SclL(void){
	HAL_GPIO_SetInOut(GPIOD, GPIO_PIN_7, ENABLE, ENABLE);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET);
}

static u8 i2c_ReadSda(void){
	return HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_6);
}

static u8 i2c_ReadScl(void){
	return HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_7);
}

//iic设备注册
void sht_i2c_init(mI2CTypedef_t *i2c)
{
	i2c->IIC_InitPort=0;
	i2c->IIC_SDA_H=i2c_SdaH;
	i2c->IIC_SDA_L=i2c_SdaL;
	i2c->IIC_SCL_H=i2c_SclH;
	i2c->IIC_SCL_L=i2c_SclL;
	i2c->IIC_READ_SDA=i2c_ReadSda;
	i2c->IIC_READ_SCL=i2c_ReadScl;
}

//时序来自芯片手册
void sht_cmd_write(u8 cmd)
{
	i2c_Start(&ShtI2c);
	i2c_SendByte(&ShtI2c,SHT_ADDR|I2C_WR);
	i2c_WaitAck(&ShtI2c);
	i2c_SendByte(&ShtI2c,cmd);
	i2c_WaitAck(&ShtI2c);
	i2c_Stop(&ShtI2c);
}

//温度高 温度低 温度crc 湿度高 湿度低 湿度crc
//示例 65 08 1A 83 6B DE
u8 sht_ack_read(u8 *buf)
{
	u8 len=6;
	i2c_Start(&ShtI2c);
	i2c_SendByte(&ShtI2c,SHT_ADDR|I2C_RD);
	if(1==i2c_WaitAck(&ShtI2c)){	//ERROR
		goto ERR;
	}
	while(len-->1){
		*buf++ = i2c_ReadByte(&ShtI2c);
		i2c_Ack(&ShtI2c);
	}
	*buf++ = i2c_ReadByte(&ShtI2c);
	i2c_NAck(&ShtI2c);
	i2c_Stop(&ShtI2c);
	return 0;//正常返回
ERR:
	i2c_SdaErrorClear(&ShtI2c);
	return 1;	
}

u8 sht_crc8(const u8 *data1, u16 len) 
{
	const u8 POLYNOMIAL=0x31;
	u8 crc=0xFF;

	for (int j = len; j; --j) {
		crc ^= *data1++;

		for (int i = 8; i; --i) {
			crc = (crc & 0x80) ? (crc << 1) ^ POLYNOMIAL : (crc << 1);
		}
	}
	return crc;
}

//初始化
void sht_init(void)
{
	sht_i2c_init(&ShtI2c);
}



/*
4.1 I2C通信

I2C通信基于恩智浦的I2C总线规范和用户手册UM10204，修订版62014年4月4日。
支持的I2C模式有标准模式、快速模式和快速模式+。
数据以16位字和8位校验和的倍数传输（循环冗余校验＝CRC）。
所有传输必须以开始条件（S）开始，以停止条件（P）结束。要完成读取传输，请发送未确认（NACK）和停止条件（P）。
寻址特定的从设备是通过发送其7位I2C地址和第八位来完成的，第八位表示通信方向：“零”表示向从设备的传输，即“写”，“一”表示“读”请求。
I2C传输类型的示意图如图8所示。传感器不支持时钟拉伸。
如果传感器接收到读取标头并且仍忙于测量或加热，则它将返回NACK。
测量数据只能接收一次，并且将在第一个确认的I2C读取标头之后从传感器的寄存器中删除。

图8:I2C传输类型：首先向I2C从设备发送一个写头，然后是一个命令，例如“以最高精度测量RH&T”。
测量完成后，将确认指向该I2C从设备的读取请求，并由从设备开始数据传输。

4.2数据类型和长度

I2C总线使用8位数据包进行操作。从传感器到主机的信息在每第二个8位数据包之后都有一个校验和。
湿度和温度数据将始终以以下方式传输：第一个值是温度信号（2*8位数据+8位CRC），第二个值是湿度信号（2*8位数据+8位CRC）。
高字节优先传输。

4.3校验计算 crc8

4.4命令列表

命令字     应答长度（包括crc）			描述
0xFD		6						高精度（高重复性）测量T和RH  [2*8位T-数据；8位CRC；2*8位RH数据；8比特CRC]
0xF6		6						中精度（中重复性）测量T和RH  [2*8位T-数据；8位CRC；2*8位RH数据；8比特CRC]
0xE0		6						低精度（低重复性）测量T和RH  [2*8位T-数据；8位CRC；2*8位RH数据；8比特CRC]
0x89		6						读取唯一序列号   [2*8位数据；8位CRC；2*8位数据，8位CRC]
0x94		6						软复位			[ack]
0x39		6						用200mW激活加热器1s，包括在停用前进行高精度测量[2*8位T-数据；8位CRC；2*8位RH数据；8比特CRC]
0x32		6						用200mW激活加热器0.11s，包括在停用前进行高精度测量[2*8位T-数据；8位CRC；2*8位RH数据；8比特CRC]
0x2F		6						用110mW激活加热器1s，包括在停用前进行高精度测量[2*8位T-数据；8位CRC；2*8位RH数据；8比特CRC]
0x24		6						用110mW激活加热器0.1s，包括在停用前进行高精度测量[2*8位T-数据；8位CRC；2*8位RH数据；8比特CRC]
0x1E		6						用20mW激活加热器1s，包括在停用前进行高精度测量[2*8位T-数据；8位CRC；2*8位RH数据；8比特CRC]
0x15		6						用20mW激活加热器0.1s，包括在停用前进行高精度测量[2*8位T-数据；8位CRC；2*8位RH数据；8比特CRC]


表7 I2C命令概述。如果传感器还没有准备好处理命令，例如因为它仍在测量，它将用NACK对I2C读取报头进行响应。
给定的加热器功率值是典型的，并且对于VDD=3.3V有效。

4.5数值计算

注意：RH转换公式（1）允许报告在0%RH…100%RH范围之外的值。
小于0%RH和大于100%RH的相对湿度值是非物理的，但在某些情况下（例如，当感兴趣的是传感器在测量边界的分布时），可能会发现这些“非交叉”值是有益的。
对于所有不想参与评估这些非物理值的用户，建议将RH信号裁剪到0%RH…100%RH的范围。



4.6序列号

每个传感器都有一个唯一的序列号，由Sensionon在生产过程中分配。
它存储在一次性可编程存储器中，生产后无法操作。
序列号可通过I2C命令0x89访问，并作为两个16位字传输，每个字后面跟着一个8位CRC。

4.7重置和中止

传感器的重置可以通过三种方式实现：

•软复位：发送表7中所述的复位命令。
•I2C通用调用重置：通过向I2C地址0x00发送命令0x06，重置I2C总线上的所有设备。
•断电（包括将SCL和SDA拉低）

任何触发传感器动作的命令都可以通过I2C通用调用重置或软重置中止。

4.8加热器操作

该传感器包含一个集成的片上加热器，可以通过表7中给出的一组命令打开。可选择三种加热功率和两种加热持续时间。在接收到加热器打开命令后，传感器执行以下程序：

1.加热器已启用，计时器开始倒计时
2.定时器到期时，启动可重复性最高的温度和湿度测量，加热器保持启用状态
3.测量完成后，关闭加热器
4.现在可以获得温度和湿度值

加热器命令的最大接通时间为1秒，以防止由于加热器的意外使用而导致传感器过热。
因此，不存在关闭加热器的专用命令。
对于延长的加热周期，需要发送周期性的加热器开启命令，记住加热器的设计最大占空比小于5%。
为了快速提高温度，连续加热脉冲之间的空闲时间应保持在最低限度。



*/

